home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / p063b9s.zip / UNIT / BTREE.PAS < prev    next >
Pascal/Delphi Source File  |  1996-04-20  |  10KB  |  346 lines

  1. UNIT BTree;
  2. {╔══════════════════════════════════════════════════════════════════════════╗}
  3. {║ BTree routines for Opus 1.73a                 Last changed: 20.04.96  SA ║}
  4. {║                                                                          ║}
  5. {║                         (C) Copyright 1989-93 by                         ║}
  6. {║       Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager        ║}
  7. {║                         ,Birger Kristensen                               ║}
  8. {║ This source may not be given to anybody, without the written permission  ║}
  9. {║ from The Portal Team.                                                    ║}
  10. {╚══════════════════════════════════════════════════════════════════════════╝}
  11. {$I POPDEFS.INC}
  12.  
  13. INTERFACE
  14.  
  15. USES Use32, PoPTypes, Dos;
  16.  
  17. TYPE
  18.   FindType = (Previous,Match,Next);
  19.   CompProc = function(var ALine,Desire; L:char):integer;
  20.  
  21.   TA=RECORD
  22.     Fill   : BYTE;
  23.     Zone,
  24.     Net,
  25.     Node,
  26.     Point  : INTEGER;
  27.   END;
  28.  
  29.   CtlBlk = record
  30.     BlkSize : word;
  31.     Root,
  32.     HiBlk,
  33.     LoLeaf,
  34.     HiLeaf,
  35.     Free : longint;
  36.     Lvls,
  37.     Parity : word;
  38.   end;
  39.  
  40.   IdxRefBlk = record
  41.     IdxOfs,
  42.     IdxLen : word;
  43.     IdxData,
  44.     IdxPtr : longint;
  45.   end;
  46.  
  47.   LeafRefBlk = record
  48.     KeyOfs,
  49.     KeyLen : word;
  50.     KeyVal : longint;
  51.   end;
  52.  
  53.   INodeBlk = record
  54.     First,
  55.     BLink,
  56.     FLink : LongInt;
  57.     Cnt   : Integer;
  58.     StrOf : Word;
  59.     IdxRef : array[0..49] of IdxRefBlk;
  60.   end;
  61.  
  62.   LNodeBlk = record
  63.     First,
  64.     BLink,
  65.     FLink : longint;
  66.     Cnt : integer;
  67.     StrOf : word;
  68.     LeafRef : array[0..49] of LeafRefBlk;
  69.   end;
  70.  
  71.   RealDatRec = record
  72.     Zone,
  73.     Net,
  74.     Node,
  75.     Point : integer;
  76.     CallCost,
  77.     MsgFee,
  78.     NodeFlags : word;
  79.     ModemType,
  80.     PhoneLen,
  81.     PassWordLen,
  82.     BNameLen,
  83.     SNameLen,
  84.     CNameLen,
  85.     PackLen,
  86.     Baud : byte;
  87.     Pack : array[1..160] of char;
  88.   end;
  89.  
  90.   DatRec = record
  91.     Zone,
  92.     Net,
  93.     Node,
  94.     Point : integer;
  95.     CallCost,
  96.     MsgFee,
  97.     NodeFlags : word;
  98.     ModemType,
  99.     Password : string[9];
  100.     Phone,
  101.     BName,
  102.     CName,
  103.     SName : string[39];
  104.     BaudRate,
  105.     RecSize : byte;
  106.   end;
  107.  
  108.   KeyStr=S30;
  109.  
  110. FUNCTION FindKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  111. FUNCTION NextKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  112. FUNCTION PrevKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  113.  
  114. IMPLEMENTATION
  115.  
  116. USES NetFile;
  117.  
  118. function CompName(var S,D; L:char):integer; far;
  119. var
  120.   Key,Des : S160;
  121.   Len : byte absolute L;
  122.  
  123. begin
  124.   Key[0]:=L;
  125.   Des[0]:=L;
  126.   Move(S,Key[1],Len);
  127.   Move(D,Des[1],Len);
  128.   if Key>Des then CompName:=1 else
  129.     if Key<Des then CompName:=-1 else CompName:=0;
  130. end;
  131.  
  132. {
  133. function CompAddress(var S,D; L:char):integer; far;
  134. var
  135.   Key : TA absolute S;
  136.   Des : TA absolute D;
  137.   I : byte;
  138.   K : integer;
  139.  
  140. begin
  141.   IF l=#6 THEN Des.Point:=0;
  142.   I:=0;
  143.   repeat
  144.     Inc(I);
  145.     case I of
  146.       1 : K:=Key.Zone-Des.Zone;
  147.       2 : K:=Key.Net-Des.Net;
  148.       3 : K:=Key.Node-Des.Node;
  149.       4 : begin
  150.             if L=#6 then Key.Point:=0;
  151.             K:=Key.Point-Des.Point;
  152.           end;
  153.     end;
  154.   until (I=4) or (K<>0);
  155.   CompAddress:=K;
  156. end;
  157. }
  158.  
  159.   FUNCTION CompAddress(VAR s, d; l:CHAR): Integer;
  160.   TYPE
  161.     AT = RECORD
  162.       Len : Byte;
  163.       zone,net,node,point: Integer;
  164.     END;
  165.   VAR
  166.     k : Integer;
  167.   BEGIN
  168.     k:=AT(s).Zone-AT(d).Zone;
  169.     IF k=0 THEN
  170.     BEGIN
  171.       k:=AT(s).Net-AT(d).Net;
  172.       IF k=0 THEN
  173.       BEGIN
  174.         k:=AT(s).Node-AT(d).Node;
  175.         IF k=0 THEN
  176.         BEGIN
  177.           IF BYTE(s)=6 THEN AT(s).Point:=0;
  178.           IF BYTE(d)=6 THEN AT(d).Point:=0;
  179.           k:=AT(s).Point-AT(d).Point;
  180.         END;
  181.       END;
  182.     END;
  183.     CompAddress:=k;
  184.   END;
  185.  
  186.  
  187. function Find(var F: TNetFile; Desired:S160; Compare:CompProc; var KeyL:byte; FT:FindType):longint;
  188. var
  189.   Buf : array[0..511] of byte;
  190.   Ctl : CtlBlk absolute Buf;
  191.   INode : INodeBlk absolute Buf;
  192.   LNode : LNodeBlk absolute Buf;
  193.   SaveCtl : CtlBlk;
  194.   count : byte;
  195.   currentblocknumber : longint;
  196.   difference : integer;
  197.   s : string;
  198. begin
  199.   f.Seek(0);
  200.   f.BlockRead(Buf,SizeOf(Buf));
  201.   Move(Buf,SaveCtl,SizeOf(Ctl));
  202.   f.Seek(SaveCtl.BlkSize*Ctl.Root);
  203.   f.BlockRead(Buf,SizeOf(Buf));
  204.   currentblocknumber := -1;
  205.   count := 0;
  206.   While INode.First <> -1 do { S¢g i indexblokke, indtil leafnode er fundet }
  207.     begin
  208.       difference := -1;
  209.       While (count < INode.Cnt) and (difference < 0) do
  210.         begin
  211.           FillChar(S,SizeOf(S),#0);
  212.           Move(Buf[INode.IdxRef[count].IdxOfs],S[1],INode.IdxRef[count].IdxLen);
  213.           BYTE(s[0]):=INode.IdxRef[count].IdxLen;
  214.           difference := Compare(S,Desired,Chr(inode.IdxRef[count].IdxLen));
  215.           if (difference = 0) AND (FT = Match) then { Her afslutter s¢gning, hvis Match }
  216.            begin
  217.              Find:=INode.IdxRef[count].IdxData;
  218.              KeyL:=INode.IdxRef[count].IdxLen;
  219.              exit;
  220.            end;
  221.           IF difference < 0 THEN INC (Count); { move to right (i.e. Increment count) until difference >= 0 }
  222.         end;
  223.       IF difference = 0 then currentblocknumber := inode.IdxRef[Count].IdxPtr
  224.         else IF Count = 0 THEN currentblocknumber := inode.First
  225.                ELSE currentblocknumber := inode.IdxRef[Count-1].IdxPtr;
  226.       f.Seek(SaveCtl.BlkSize*currentblocknumber);
  227.       f.BlockRead(Buf,SizeOf(Buf));
  228.       count := 0;
  229.     end;
  230.   difference := -1;
  231.   count := 0;
  232.   while (count < LNode.Cnt) and (difference < 0) do { Vi har nu fundet leafblokken }
  233.    begin
  234.           FillChar(S,SizeOf(S),#0);
  235.           Move(Buf[lNode.leafRef[count].keyOfs],S[1],lNode.leafRef[count].keyLen);
  236.           BYTE(s[0]):=lNode.leafRef[count].keyLen;
  237.           difference := Compare(S,Desired,Chr(lnode.leafRef[count].keyLen));
  238.           if difference = 0 then
  239.            begin
  240.              case FT of
  241.                Previous : begin
  242.                             if count > 0 then
  243.                               begin
  244.                                 find:=lNode.leafRef[count-1].keyVal;
  245.                                 KeyL:=lNode.leafRef[count-1].keyLen;
  246.                               end
  247.                             else
  248.                               begin
  249.                                 if Lnode.blink <> 0 then
  250.                                   begin
  251.                                     f.Seek(SaveCtl.BlkSize*Lnode.blink);
  252.                                     f.BlockRead(Buf,SizeOf(Buf));
  253.                                     find:=lnode.LeafRef[lnode.cnt-1].KeyVal;
  254.                                     KeyL:=lnode.LeafRef[lnode.cnt-1].KeyLen;
  255.                                   end
  256.                                 else
  257.                                  begin
  258.                                    find:=lnode.LeafRef[0].KeyVal;
  259.                                    KeyL:=lnode.LeafRef[0].KeyLen;
  260.                                  end;
  261.                               end;
  262.                           end;
  263.                Match    : begin
  264.                             find:=lnode.LeafRef[count].KeyVal;
  265.                             KeyL:=lnode.LeafRef[count].KeyLen;
  266.                           end;
  267.                Next     : begin
  268.                             if count < lnode.cnt-1 then
  269.                               begin
  270.                                 find:=lnode.LeafRef[count+1].KeyVal;
  271.                                 KeyL:=lnode.LeafRef[count+1].KeyLen;
  272.                               end
  273.                             else
  274.                               begin
  275.                                 if Lnode.flink <> 0 then
  276.                                   begin
  277.                                     f.Seek(SaveCtl.BlkSize*Lnode.flink);
  278.                                     f.BlockRead(Buf,SizeOf(Buf));
  279.                                     find:=lNode.leafRef[0].keyval;
  280.                                     KeyL:=lNode.leafRef[0].keyLen;
  281.                                   end
  282.                                 else
  283.                                  begin
  284.                                    find:=lnode.LeafRef[lnode.cnt-1].KeyVal;
  285.                                    KeyL:=lnode.LeafRef[lnode.cnt-1].KeyLen;
  286.                                  end;
  287.                               end;
  288.                           end;
  289.              end;
  290.            end;
  291.      IF difference < 0 THEN INC (Count); { move to right (i.e. Increment count) until difference >= 0 }
  292.      IF (difference>0) OR (Count=LNode.Cnt) THEN
  293.      BEGIN
  294.        Count:=LNode.Cnt;
  295.        Find:=-1;
  296.      END;
  297.    end;
  298. end;
  299.  
  300.  
  301. FUNCTION FindKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  302. VAR
  303.   Idx : TNetFile;
  304.   Kl  : BYTE;
  305. BEGIN
  306.   FindKey:=FALSE;
  307.   IF Idx.Open(FName,1,FALSE) THEN
  308.   BEGIN
  309.     RecNum:=Find(Idx,Desired,CompAddress,Kl,Match);
  310.     Idx.Close;
  311.     FindKey:=(RecNum<>-1);
  312.   END;
  313. END;
  314.  
  315. FUNCTION NextKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  316. VAR
  317.   Idx : TNetFile;
  318.   Kl  : BYTE;
  319. BEGIN
  320.   NextKey:=FALSE;
  321.   IF Idx.Open(FName,1,FALSE) THEN
  322.   BEGIN
  323.     RecNum:=Find(Idx,Desired,CompAddress,Kl,Next);
  324. {    NextKey:=TRUE;}
  325.     NextKey:=(RecNum<>-1);
  326.     Idx.Close;
  327.   END;
  328. END;
  329.  
  330. FUNCTION PrevKey(CONST FName: PathStr; VAR RecNum: LongInt; CONST Desired: KeyStr): Boolean;
  331. VAR
  332.   Idx : TNetFile;
  333.   Kl  : BYTE;
  334. BEGIN
  335.   PrevKey:=FALSE;
  336.   IF Idx.Open(FName,1,FALSE) THEN
  337.   BEGIN
  338. {    PrevKey:=TRUE;}
  339.     RecNum:=Find(Idx,Desired,CompAddress,Kl,Previous);
  340.     PrevKey:=(RecNum<>-1);
  341.     Idx.Close;
  342.   END;
  343. END;
  344.  
  345. END.
  346.